﻿@page "/radialGradientBrush"
@using VectSharp;
@using VectSharp.SVG;

<style>
	table {
		table-layout: fixed;
	}

	td {
		width: 200px;
		padding: 10px;
	}
</style>

<div style="width: 100vw; height: 100vh; position: relative;">
	<div style="width: calc(100% - 440px); height: 100%; position: absolute; top: 0; left: 0; text-align: center">
		<img src="@imgSource" style="max-width: 100%; max-height: 100%; margin-top: 50vh; transform: translate(0, -50%)" />
	</div>

	<div style="width: 440px; height: 100vh; position: absolute; top: 0; right: 0;">
		<table style="margin-top: 50vh; transform: translate(0, -50%)">
			<tr>
				<td style="width: 20px">
					<span class="oi oi-media-record" title="media-record" aria-hidden="true" style="color: #56B4E9"></span>
				</td>
				<td>
					<MatNumericUpDownField Label="Focal point X"
										   @bind-Value=@p1X
										   Step="1">
					</MatNumericUpDownField>
				</td>
				<td>
					<MatNumericUpDownField Label="Focal point Y"
										   @bind-Value=@p1Y
										   Step="1">
					</MatNumericUpDownField>
				</td>
			</tr>
			<tr>
				<td style="width: 20px">
					<span class="oi oi-star" title="star" aria-hidden="true" style="color: #009E73"></span>
				</td>
				<td colspan="2" style="width: 400px;">
					<div style="display: inline-block; position: relative; width: 380px">
						<span class="mdc-floating-label mdc-floating-label--float-above" style="margin-left:0.5em; margin-top: 2em; color: rgba(0, 0, 0, 0.6)">Intermediate point</span><br />
						<div style="position: relative">
							<div style="display: inline-block; width: 300px">
								<MatSlider ValueMin="0" ValueMax="100" @bind-Value="@intermediate" Immediate="true"></MatSlider>
							</div>
							<span style="position: absolute; top: 50%; left: 320px; transform: translate(0, -50%)">@((intermediate / 100).ToString("0.00", System.Globalization.CultureInfo.InvariantCulture))</span>
						</div>
					</div>
				</td>
			</tr>
			<tr>
				<td style="width: 20px">
					<span class="oi oi-media-stop" title="media-stop" aria-hidden="true" style="color: #0072B2"></span>
				</td>
				<td>
					<MatNumericUpDownField Label="Centre X"
										   @bind-Value=@p2X
										   Step="1">
					</MatNumericUpDownField>
				</td>
				<td>
					<MatNumericUpDownField Label="Centre Y"
										   @bind-Value=@p2Y
										   Step="1">
					</MatNumericUpDownField>
				</td>
			</tr>
			<tr>
				<td style="width: 20px"> </td>
				<td colspan="2" style="width: 400px; text-align: center">
					<MatNumericUpDownField Label="Radius"
										   @bind-Value=@gradientRadius
										   Minimum="0"
										   Step="1">
					</MatNumericUpDownField>
				</td>
			</tr>

		</table>
	</div>
</div>

@code {
	private double _p1X = 30;
	private double p1X
	{
		get
		{
			return _p1X;
		}

		set
		{
			_p1X = value;
			Render();
		}
	}

	private double _p1Y = 30;
	private double p1Y
	{
		get
		{
			return _p1Y;
		}

		set
		{
			_p1Y = value;
			Render();
		}
	}

	private double _p2X = 50;
	private double p2X
	{
		get
		{
			return _p2X;
		}

		set
		{
			_p2X = value;
			Render();
		}
	}

	private double _p2Y = 50;
	private double p2Y
	{
		get
		{
			return _p2Y;
		}

		set
		{
			_p2Y = value;
			Render();
		}
	}

	private double _intermediate = 50;
	private double intermediate
	{
		get
		{
			return _intermediate;
		}

		set
		{
			_intermediate = value;
			Render();
		}
	}

	private double _gradientRadius = 40;
	private double gradientRadius
	{
		get
		{
			return _gradientRadius;
		}

		set
		{
			_gradientRadius = value;
			Render();
		}
	}

	private string imgSource = "";

	protected override Task OnInitializedAsync()
	{
		Render();
		return Task.CompletedTask;
	}

	public void Render()
	{
		Page page = new Page(100, 100);
		Graphics graphics = page.Graphics;

		GradientStop start = new GradientStop(Colour.FromRgb(86, 180, 233), 0);
		GradientStop middle = new GradientStop(Colour.FromRgb(0, 158, 115), intermediate / 100.0);
		GradientStop end = new GradientStop(Colour.FromRgb(0, 114, 178), 1);
		RadialGradientBrush brush = new RadialGradientBrush(new Point(p1X, p1Y), new Point(p2X, p2Y), gradientRadius, start, middle, end);

		graphics.FillRectangle(10, 10, 80, 80, brush);

		graphics.FillPath(new GraphicsPath().Arc(p1X, p1Y, 2, 0, 2 * Math.PI), Colour.FromRgb(180, 180, 180));
		graphics.FillRectangle(p2X - 2, p2Y - 2, 4, 4, Colour.FromRgb(180, 180, 180));

		Point starCentre = new Point(p1X * (1 - intermediate / 100.0) + p2X * intermediate / 100.0, p1Y * (1 - intermediate / 100.0) + p2Y * intermediate / 100.0);

		GraphicsPath star = new GraphicsPath();
		GraphicsPath starOuter = new GraphicsPath();
		double starRadius = 3;
		for (int i = 0; i < 10; i++)
		{
			double radius = i % 2 == 0 ? starRadius : (starRadius * 0.5);

			star.LineTo(starCentre.X + radius * Math.Sin(i * Math.PI / 5), starCentre.Y + radius * Math.Cos(i * Math.PI / 5));
			starOuter.LineTo(starCentre.X + radius * 1.5 * Math.Sin(i * Math.PI / 5), starCentre.Y + radius * 1.5 * Math.Cos(i * Math.PI / 5));
		}
		star.Close();
		starOuter.Close();
		starOuter.MoveTo(0, 0).LineTo(100, 0).LineTo(100, 100).LineTo(0, 100).Close();
		graphics.Save();
		graphics.SetClippingPath(starOuter);

		Point perp = new Point(p2Y - p1Y, p1X - p2X);
		double modulus = perp.Modulus();
		/*perp = new Point(perp.X / modulus, perp.Y / modulus);
		graphics.StrokePath(new GraphicsPath().MoveTo(p1X - perp.X * 142, p1Y - perp.Y * 142).LineTo(p1X + perp.X * 142, p1Y + perp.Y * 142), Colour.FromRgb(180, 180, 180), 0.5, lineDash: new LineDash(2.5, 2.5, 0));
		graphics.StrokePath(new GraphicsPath().MoveTo(p2X - perp.X * 142, p2Y - perp.Y * 142).LineTo(p2X + perp.X * 142, p2Y + perp.Y * 142), Colour.FromRgb(180, 180, 180), 0.5, lineDash: new LineDash(2.5, 2.5, 0));
		graphics.StrokePath(new GraphicsPath().MoveTo(starCentre.X - perp.X * 142, starCentre.Y - perp.Y * 142).LineTo(starCentre.X + perp.X * 142, starCentre.Y + perp.Y * 142), Colour.FromRgb(180, 180, 180), 0.5, lineDash: new LineDash(2.5, 2.5, 0));*/

		graphics.StrokePath(new GraphicsPath().MoveTo(p1X, p1Y).LineTo(p2X, p2Y), Colour.FromRgb(180, 180, 180), lineDash: new LineDash(5, 5, 0));
		graphics.Restore();

		graphics.StrokePath(new GraphicsPath().Arc(p2X, p2Y, gradientRadius, 0, 2 * Math.PI), Colour.FromRgb(180, 180, 180), lineDash: new LineDash(5, 5, 0));

		graphics.StrokePath(new GraphicsPath().Arc(starCentre, gradientRadius * intermediate / 100.0, 0, 2 * Math.PI), Colour.FromRgb(180, 180, 180), 0.5, lineDash: new LineDash(2.5, 2.5, 0));

		graphics.FillPath(star, Colour.FromRgb(180, 180, 180));

		using (MemoryStream ms = new MemoryStream())
		{
			page.SaveAsSVG(ms);
			ms.Seek(0, SeekOrigin.Begin);

			using (StreamReader sr = new StreamReader(ms))
			{
				this.imgSource = "data:image/svg+xml;base64," + Convert.ToBase64String(System.Text.Encoding.UTF8.GetBytes(sr.ReadToEnd()));
			}
		}
	}
}
